/*
 * Copyright (c) 2005 -2008 Reliable Source, Inc. and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Mozilla Public License v.1.1,
 * BSD, and Eclipse Public License v1.0 which accompanies this
 * distribution and is available at:
 *
 * 		http://www.eclipse.org/legal/epl-v10.html
 * 		http://www.opensource.org/licenses/bsd-license.php
 * 		http://www.mozilla.org/MPL/MPL-1.1.html
 *
 * Contributors:
 *     IBM Corporation	     -  http://ibm.com
 *     	- initial API and implementation
 *
 *     patientos.org         - http://patientos.org
 *     	- domain and database persistence layer
 *
 *     Reliable Source, Inc. - http://reliablesource.org
 *     	- Symbiosys Application Framework,
 *     	- Symbiosys Application, Symbiosys Product
 *
 */
package org.reliablesource.symbiosys.platform.viewers;

import com.patientis.client.service.med.MedService;
import com.patientis.client.service.patient.PatientService;
import com.patientis.client.state.State;

import com.patientis.model.common.AddressModel;
import com.patientis.model.common.ContactModel;
import com.patientis.model.common.EmailModel;
import com.patientis.model.common.IBaseModel;
import com.patientis.model.common.ModelField;
import com.patientis.model.common.ModelReference;
import com.patientis.model.common.PhoneModel;
import com.patientis.model.med.MedModel;
import com.patientis.model.patient.PatientModel;
import com.patientis.model.patient.ViewPatientModel;
import com.patientis.model.reference.ContextReference;

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.DateTime;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

import org.eclipse.ui.forms.events.ExpansionAdapter;
import org.eclipse.ui.forms.events.ExpansionEvent;
import org.eclipse.ui.forms.widgets.Form;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.forms.widgets.TableWrapData;
import org.eclipse.ui.forms.widgets.TableWrapLayout;

import org.reliablesource.client.ui.symbiosys.platform.SymbiosysApplication;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;


/**
 * 
 * SymbiosysControlFactory.java<br>
 * Created on: Jun 07, 2008<br>
 *
 * @author <a href="mailto:dennis.park@gmail.com">Dennis Park</a>
 *
 * @category
 * @since 1.0
 */
public class SymbiosysControlFactory {
    public final static String[] PATIENT = {
            "Last Name", "First Name", "Middle Name", "Gender", "DOB", "SSN",
            "Marital Status", "Occupation"
        };
    public final static int LAST = 0;
    public final static int FIRST = 1;
    public final static int MIDDLE = 2;
    public final static int SEX = 3;
    public final static int DOB = 4;
    public final static int SSN = 5;
    public final static int MARITAL = 6;
    public final static int OCCUPATION = 7;
    public final static String[] ADDRESS = {
            "Line 1", "Line 2", "City", "State", "Zipcode", "Country",
            "Home Phone", "Cell Phone", "Work Phone", "Email"
        };
    public final static int LINE1 = 0;
    public final static int LINE2 = 1;
    public final static int CITY = 2;
    public final static int STATE = 3;
    public final static int ZIP = 4;
    public final static int COUNTRY = 5;
    public final static int HOME_PHONE = 6;
    public final static int CELL_PHONE = 7;
    public final static int WORK_PHONE = 8;
    public final static int EMAIL = 9;
    public final static String[] CONTACT = {
            "Spouse Last Name", "Spouse First Name",
            "Family Physician Last Name", "Family Physician First Name",
            "Family Physician Work Phone"
        };
    public final static int SPOUSE_LAST = 0;
    public final static int SPOUSE_FIRST = 1;
    public final static int PHYSICIAN_LAST = 2;
    public final static int PHYSICIAN_FIRST = 3;
    public final static int PHYSICIAN_WORK_PHONE = 4;

    /**
     * singleton instance reference
     */
    private static SymbiosysControlFactory instance;
    public HashMap<String, Control> patientControls;
    public HashMap<String, Integer> patientControlRefIds;
    FormToolkit toolkit;

    /**
     * Singleton constructor
     * @category constructor
     */
    private SymbiosysControlFactory() {
        patientControls = new HashMap<String, Control>();
        patientControlRefIds = new HashMap<String, Integer>();

        patientControlRefIds.put(PATIENT[LAST],
            new Integer(ModelReference.PATIENTS_LASTNAME));
        patientControlRefIds.put(PATIENT[FIRST],
            new Integer(ModelReference.PATIENTS_FIRSTNAME));
        patientControlRefIds.put(PATIENT[MIDDLE],
            new Integer(ModelReference.PATIENTS_MIDDLENAME));
        patientControlRefIds.put(PATIENT[SEX],
            new Integer(ModelReference.PATIENTS_GENDERREFID));
        patientControlRefIds.put(PATIENT[DOB],
            new Integer(ModelReference.PATIENTS_BIRTHDT));
        patientControlRefIds.put(PATIENT[SSN],
            new Integer(ModelReference.PATIENTS_PATIENTID));
        patientControlRefIds.put(PATIENT[MARITAL],
            new Integer(ModelReference.PATIENTS_MARITALSTATUSREFID));
        patientControlRefIds.put(PATIENT[OCCUPATION],
            new Integer(ModelReference.PATIENTS_OCCUPATION));

        patientControlRefIds.put(ADDRESS[LINE1],
            new Integer(ModelReference.ADDRESSES_STREET));
        patientControlRefIds.put(ADDRESS[LINE2],
            new Integer(ModelReference.ADDRESSES_OTHERDESIGNATION));
        patientControlRefIds.put(ADDRESS[CITY],
            new Integer(ModelReference.ADDRESSES_CITYREFID));
        patientControlRefIds.put(ADDRESS[STATE],
            new Integer(ModelReference.ADDRESSES_STATEREFID));
        patientControlRefIds.put(ADDRESS[ZIP],
            new Integer(ModelReference.ADDRESSES_POSTALCODE));
        patientControlRefIds.put(ADDRESS[COUNTRY],
            new Integer(ModelReference.ADDRESSES_COUNTRYREFID));

        patientControlRefIds.put(ADDRESS[HOME_PHONE],
            new Integer(ModelReference.PHONES_PHONEID));
        patientControlRefIds.put(ADDRESS[CELL_PHONE],
            new Integer(ModelReference.PHONES_DEVICETYPEREFID));
        patientControlRefIds.put(ADDRESS[WORK_PHONE],
            new Integer(ModelReference.PHONES_PHONETYPEREFID));
        patientControlRefIds.put(ADDRESS[EMAIL],
            new Integer(ModelReference.EMAILS_SYSTEMREFID));

        patientControlRefIds.put(CONTACT[SPOUSE_LAST],
            new Integer(ModelReference.CONTACTS_LASTNAME));
        patientControlRefIds.put(CONTACT[SPOUSE_FIRST],
            new Integer(ModelReference.CONTACTS_FIRSTNAME));

        patientControlRefIds.put(CONTACT[PHYSICIAN_LAST],
            new Integer(ModelReference.CONTACTS_SYSTEMREFID));
        patientControlRefIds.put(CONTACT[PHYSICIAN_FIRST],
            new Integer(ModelReference.CONTACTS_SYSTEMREFID));
        patientControlRefIds.put(CONTACT[PHYSICIAN_WORK_PHONE],
            new Integer(ModelReference.CONTACTS_SYSTEMREFID));
    }

    /**
     *
     * @return ICMPViewerFactory - the singleton instance
     */
    public static synchronized SymbiosysControlFactory getInstance() {
        if (instance == null)
            instance = new SymbiosysControlFactory();

        return instance;
    }

    /**
     *
     * @param _formBody
     * @model ViewPatientModel
     */
    public Composite createPatientSection(final Composite _formBody) {
        if (toolkit == null)
            toolkit = new FormToolkit(_formBody.getDisplay());

        Section section = toolkit.createSection(_formBody,
                Section.DESCRIPTION | Section.TITLE_BAR | Section.TWISTIE |
                Section.EXPANDED);

        TableWrapData td = new TableWrapData(TableWrapData.FILL_GRAB);
        td.colspan = 1;
        section.setLayoutData(td);
        section.addExpansionListener(new ExpansionAdapter() {
                public void expansionStateChanged(ExpansionEvent e) {
                    _formBody.layout(true);
                }
            });
        section.setText("Patient");
        section.setDescription("Patient Details");

        Composite sectionClient = toolkit.createComposite(section);

        ViewPatientModel model = new ViewPatientModel();
        sectionClient.setData(SymbiosysTextControlFocusListener.MODEL, model);

        GridLayout _layout = new GridLayout();
        _layout.numColumns = 6;
        _layout.marginWidth = 10;
        _layout.marginBottom = 10;
        _layout.marginLeft = 10;
        _layout.marginRight = 10;
        _layout.marginTop = 10;
        _layout.marginHeight = 10;
        sectionClient.setLayout(_layout);

        createLabelTextGridRow(sectionClient, PATIENT[LAST]);
        createLabelTextGridRow(sectionClient, PATIENT[FIRST]);
        createLabelTextGridRow(sectionClient, PATIENT[MIDDLE]);

        toolkit.createLabel(sectionClient, PATIENT[SEX]);
        patientControls.put(PATIENT[SEX],
            new Combo(sectionClient, SWT.READ_ONLY | SWT.FLAT));

        Combo _combo = ((Combo) patientControls.get(PATIENT[SEX]));
        _combo.add("Female");
        _combo.add("Male");
        _combo.select(1);

        patientControls.get(PATIENT[SEX])
                       .setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
                true));

        toolkit.createLabel(sectionClient, PATIENT[DOB]);
        patientControls.put(PATIENT[DOB],
            new DateTime(sectionClient, SWT.READ_ONLY | SWT.FLAT));
        patientControls.get(PATIENT[DOB])
                       .setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
                true));

        createLabelTextGridRow(sectionClient, PATIENT[SSN]);

        toolkit.createLabel(sectionClient, PATIENT[MARITAL]);
        patientControls.put(PATIENT[MARITAL],
            new Combo(sectionClient, SWT.READ_ONLY | SWT.FLAT));
        _combo = ((Combo) patientControls.get(PATIENT[MARITAL]));
        _combo.add("Divorced");
        _combo.add("Married");
        _combo.add("Separated");
        _combo.add("Single");
        _combo.select(1);
        _combo.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

        createLabelTextGridRow(sectionClient, PATIENT[OCCUPATION]);

        section.setClient(sectionClient);

        return sectionClient;
    }

    /**
     *
     * @param _formBody
     * @model AddressModel
     */
    public Composite createAddressSection(final Composite _formBody) {
        if (toolkit == null)
            toolkit = new FormToolkit(_formBody.getDisplay());

        Section section = toolkit.createSection(_formBody,
                Section.DESCRIPTION | Section.TITLE_BAR | Section.TWISTIE |
                Section.EXPANDED);

        TableWrapData td = new TableWrapData(TableWrapData.FILL_GRAB);
        td.colspan = 1;
        section.setLayoutData(td);
        section.addExpansionListener(new ExpansionAdapter() {
                public void expansionStateChanged(ExpansionEvent e) {
                    _formBody.layout(true);
                }
            });

        section.setText("Address");
        section.setDescription("Address Details");

        Composite sectionClient = toolkit.createComposite(section);

        //      Set model
        AddressModel model = new AddressModel();
        sectionClient.setData(SymbiosysTextControlFocusListener.MODEL, model);

        GridLayout _layout = new GridLayout();
        _layout.numColumns = 6;
        _layout.marginWidth = 10;
        _layout.marginBottom = 10;
        _layout.marginLeft = 10;
        _layout.marginRight = 10;
        _layout.marginTop = 10;
        _layout.marginHeight = 10;
        sectionClient.setLayout(_layout);

        createLabelTextGridRow(sectionClient, ADDRESS[LINE1], 5);
        createLabelTextGridRow(sectionClient, ADDRESS[LINE2], 5);
        createLabelTextGridRow(sectionClient, ADDRESS[CITY]);

        toolkit.createLabel(sectionClient, ADDRESS[STATE]);
        patientControls.put(ADDRESS[STATE],
            new Combo(sectionClient, SWT.READ_ONLY | SWT.FLAT));

        Combo _combo = ((Combo) patientControls.get(ADDRESS[STATE]));
        _combo.add("California");
        _combo.add("Michigan");
        _combo.add("Nebraska");
        _combo.select(1);

        GridData _gd = new GridData(SWT.FILL, SWT.FILL, true, true);
        _gd.horizontalSpan = 1;

        _combo.setLayoutData(_gd);

        createLabelTextGridRow(sectionClient, ADDRESS[ZIP], 1);

        toolkit.createLabel(sectionClient, ADDRESS[COUNTRY]);
        patientControls.put(ADDRESS[COUNTRY],
            new Combo(sectionClient, SWT.READ_ONLY | SWT.FLAT));
        _combo = ((Combo) patientControls.get(ADDRESS[COUNTRY]));
        _combo.add("United States of America");
        _combo.add("Canada");
        _combo.add("Mexico");
        _combo.add("Netherlands");
        _combo.add("South Korea");
        _combo.add("North Korea");
        _combo.add("Japan");
        _combo.add("China");
        _combo.select(0);
        _combo.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

        Group _phoneGroup = new Group(sectionClient, SWT.NONE);
        _gd = new GridData(SWT.FILL, SWT.FILL, true, true);
        _gd.horizontalSpan = 6;
        _phoneGroup.setLayoutData(_gd);
        _layout = new GridLayout();
        _layout.numColumns = 6;
        _phoneGroup.setLayout(_layout);

        _phoneGroup.setText("Phone Numbers");

        createLabelTextGridRow(_phoneGroup, ADDRESS[HOME_PHONE], 1)
            .setData(SymbiosysTextControlFocusListener.MODEL, new PhoneModel());
        createLabelTextGridRow(_phoneGroup, ADDRESS[CELL_PHONE], 1)
            .setData(SymbiosysTextControlFocusListener.MODEL, new PhoneModel());
        createLabelTextGridRow(_phoneGroup, ADDRESS[WORK_PHONE], 1)
            .setData(SymbiosysTextControlFocusListener.MODEL, new PhoneModel());

        Group _emailGroup = new Group(sectionClient, SWT.NONE);
        _gd = new GridData(SWT.FILL, SWT.FILL, true, true);
        _gd.horizontalSpan = 6;
        _emailGroup.setLayoutData(_gd);

        _layout = new GridLayout();
        _layout.numColumns = 6;
        _emailGroup.setLayout(_layout);

        //        _emailGroup.setText("Email");
        createLabelTextGridRow(_emailGroup, ADDRESS[EMAIL])
            .setData(SymbiosysTextControlFocusListener.MODEL, new EmailModel());

        section.setClient(sectionClient);

        return sectionClient;
    }

    public Text createLabelTextGridRow(final Composite _parent,
        final String _controlKey, int _horizontalSpan) {
        if (toolkit == null)
            toolkit = new FormToolkit(_parent.getDisplay());

        toolkit.createLabel(_parent, _controlKey + " : ", SWT.RIGHT);
        patientControls.put(_controlKey, toolkit.createText(_parent, ""));

        GridData _gd = new GridData(SWT.FILL, SWT.FILL, true, true);
        _gd.horizontalSpan = _horizontalSpan;
        patientControls.get(_controlKey).setLayoutData(_gd);

        final Text _text = (Text) patientControls.get(_controlKey);

        String _refId = Integer.toString(patientControlRefIds.get(_controlKey));
        _text.setData(_refId, patientControlRefIds.get(_controlKey));
        _text.addFocusListener(new SymbiosysTextControlFocusListener(
                patientControlRefIds.get(_controlKey)));

        return _text;
    }

    /**
     * GridRow span is 2 - this total includes label, and text controls.
     * @param _parent
     * @param _controlKey
     */
    public Text createLabelTextGridRow(Composite _parent, String _controlKey) {
        return createLabelTextGridRow(_parent, _controlKey, 1);
    }

    /**
     *
     * Creates a Contact Details Section.
     * @param _formBody
     * @model ContactModel
     */
    public Composite createContactsSection(final Composite _formBody) {
        if (toolkit == null)
            toolkit = new FormToolkit(_formBody.getDisplay());

        Section section = toolkit.createSection(_formBody,
                Section.DESCRIPTION | Section.TITLE_BAR | Section.TWISTIE |
                Section.EXPANDED);
        TableWrapData td = new TableWrapData(TableWrapData.FILL_GRAB);
        td.colspan = 1;
        section.setLayoutData(td);
        section.addExpansionListener(new ExpansionAdapter() {
                public void expansionStateChanged(ExpansionEvent e) {
                    _formBody.layout(true);
                }
            });
        section.setText("Contacts");
        section.setDescription("Contact Details");

        Composite sectionClient = toolkit.createComposite(section);

        ContactModel model = new ContactModel();
        sectionClient.setData(SymbiosysTextControlFocusListener.MODEL, model);

        GridLayout _layout = new GridLayout();
        _layout.numColumns = 6;
        _layout.marginWidth = 10;
        _layout.marginBottom = 10;
        _layout.marginLeft = 10;
        _layout.marginRight = 10;
        _layout.marginTop = 10;
        _layout.marginHeight = 10;
        sectionClient.setLayout(_layout);

        createLabelTextGridRow(sectionClient, CONTACT[SPOUSE_LAST], 2);
        createLabelTextGridRow(sectionClient, CONTACT[SPOUSE_FIRST], 2);

        createLabelTextGridRow(sectionClient, CONTACT[PHYSICIAN_LAST]);
        createLabelTextGridRow(sectionClient, CONTACT[PHYSICIAN_FIRST]);
        createLabelTextGridRow(sectionClient, CONTACT[PHYSICIAN_WORK_PHONE]);

        section.setClient(sectionClient);

        return sectionClient;
    }

    @Override
    final protected Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException();
    }

    public void showControls() {
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setSize(800, 600);
        shell.setLayout(new FillLayout());

        FormToolkit tk = new FormToolkit(display);
        Form form = tk.createForm(shell);
        form.setText("Register New Patient");

        TableWrapLayout _twlayout = new TableWrapLayout();
        _twlayout.numColumns = 1;
        form.getBody().setLayout(_twlayout);

        SymbiosysControlFactory.getInstance()
                               .createPatientSection(form.getBody());
        SymbiosysControlFactory.getInstance()
                               .createAddressSection(form.getBody());
        SymbiosysControlFactory.getInstance()
                               .createContactsSection(form.getBody());

        tk.adapt(form.getBody());

        shell.pack();

        shell.open();

        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
    }

    public void getPatientData() {
        List<ViewPatientModel> patients = null;

        try {
            patients = PatientService.getPatientsByPatientList(State.getUserRefId(),
                    ContextReference.PATIENTLISTMYPATIENTS.getRefId());
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.exit(1);
        }

        Iterator<ViewPatientModel> _it = patients.iterator();

        ViewPatientModel _patient;

        while (_it.hasNext()) {
            _patient = _it.next();
            System.err.println(
                "-------------ViewPatientModel------------------");
            SymbiosysControlFactory.getInstance().printFields(_patient);

            List<MedModel> meds = null;

            try {
                meds = MedService.getMedsByMedicationRefId(_patient.getId());

                Iterator<MedModel> _i = meds.iterator();

                while (_i.hasNext()) {
                    MedModel _m = _i.next();
                    System.err.println(
                        "-------------MedModel------------------");
                    SymbiosysControlFactory.getInstance().printFields(_m);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

            try {
                PatientModel _pmodel = PatientService.getPatient(_patient.getId());

                System.err.println(
                    "-------------PatientModel------------------");
                SymbiosysControlFactory.getInstance().printFields(_pmodel);
            } catch (Exception e) {
                e.printStackTrace();
            }

            //        Iterator <AllergyModel> _ai= _pmodel.getAllergies().iterator();
            //        
            //        
            //        while(_ai.hasNext()){
            //            AllergyModel _a = _ai.next();
            //            
            //            System.err.println("-------------AllergyModel------------------");
            //            SymbiosysControlFactory.getInstance().printFields(_a);
            //        }
            //        }catch(Exception e){
            //            
            //        }
            //        
            //        List<MedModel> meds = null;
            //        try {
            ////         meds = ClinicalService.getMedsByMedicationRefId(_patient.getId());
            //         Iterator<MedModel> _i = meds.iterator();
            //         while(_i.hasNext()){
            //             MedModel _m = _i.next();
            //             SymbiosysControlFactory.getInstance().printFields(_m);
            //             
            //         }
            //     } catch (Exception e) {
            //         // TODO Auto-generated catch block
            //         e.printStackTrace();
            //     }
            //        
            //        }
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        SymbiosysApplication.connect();
        getInstance().getPatientData();

        //        getInstance().showControls();
    }

    public void printFields(IBaseModel _model) {
        System.err.println();
        System.err.println(
            "-----------------------------------------------------");
        System.err.println(
            "*******************START New Root********************");
        System.err.println(
            "-----------------------------------------------------");
        System.err.println();

        printFields(_model, "");

        System.err.println();
        System.err.println(
            "-----------------------------------------------------");
        System.err.println(
            "*******************END New Root**********************");
        System.err.println(
            "-----------------------------------------------------");
        System.err.println();
    }

    private void printFields(IBaseModel _model, String _indent) {
        List<ModelField> _fields = _model.getFields();
        Iterator<ModelField> _it = _fields.iterator();
        System.err.println("DisplayList Text:  " + _model.getDebugDisplay());

        while (_it.hasNext()) {
            ModelField _fld = _it.next();
            System.err.println(_indent + "\tField:\t" + _fld.getFieldName());
        }

        List<IBaseModel> _childModels = _model.getChildren();
        Iterator<IBaseModel> _childIt = _childModels.iterator();

        while (_childIt.hasNext()) {
            System.err.println();
            System.err.println(_indent +
                "^^^^^^^^^^^^^^^Start Children^^^^^^^^^^^^^^^^^^");
            System.err.println();

            IBaseModel __mdl = _childIt.next();
            printFields(__mdl, _indent + " =-> ");

            System.err.println();
            System.err.println(_indent +
                "^^^^^^^^^^^^^^^End Children^^^^^^^^^^^^^^^^^^");
            System.err.println();
        }
    }

    private void bind() {
        //        IDataBindingContext _dbcxt = DataBinding.
    }
}
